iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 25
0
Software Development

認識scala系列 第 25

Scala day 25 (Bounds)

  • 分享至 

  • xImage
  •  

Bounds

A <: B Upper bound

再了解 Upper bound 之前也先來定義一些類別 :

trait OntheRoad

trait LikeFish

abstract class Animal {
  def name: String
}

class Cat(catName: String) extends Animal with OntheRoad with LikeFish {
  def name = catName
}

class MexCat(MexCatName: String) extends Cat(MexCatName) {
  override def name = MexCatName
}

這次定義除了用 Invariant 再加上了 Upper bound,代表 A 這類別上界是 Cat,不能再往上了(最初的父類別要是 Cat).

scala> class InvariantClass[A <: Cat]
defined class InvariantClass

所以 Cat 及 MexCat 都會成功,Animal 會失敗 :

scala> new InvariantClass[Cat]
res0: InvariantClass[Cat] = InvariantClass@2248d140

scala> new InvariantClass[MexCat]
res1: InvariantClass[MexCat] = InvariantClass@5f82209e

scala> new InvariantClass[Animal]
<console>:13: error: type arguments [Animal] do not conform to class InvariantClass's type parameter bounds [A <: Cat]
       val res2 =
           ^
<console>:14: error: type arguments [Animal] do not conform to class InvariantClass's type parameter bounds [A <: Cat]
       new InvariantClass[Animal]
           ^

再定義一個 Dog 類別,這時候雖然是 InvariantClass 但由於已經定義了 Upper bound 是 Cat,所以 Dog 會出錯 :

scala> class Dog
defined class Dog

scala> new InvariantClass[Dog]
<console>:13: error: type arguments [Dog] do not conform to class InvariantClass's type parameter bounds [A <: Cat]
       val res3 =
           ^
<console>:14: error: type arguments [Dog] do not conform to class InvariantClass's type parameter bounds [A <: Cat]
       new InvariantClass[Dog]
           ^

A >: B Lower bound

這次換用 Invariant 加上了 Lower bound,代表 A 這類別下界是 Cat,不能再往下了(最後的子類別是 Cat).

scala> class InvariantClass[A >: Cat]
defined class InvariantClass

所以 Cat 的子類別 MexCat 就會失敗,而至於 Animal、OntheRoad、LikeFish 的會成功,而 Dog 跟 Cat 目前毫無關係所以繼續失敗.

scala> new InvariantClass[Cat]
res4: InvariantClass[Cat] = InvariantClass@56820446

scala> new InvariantClass[MexCat]
<console>:13: error: type arguments [MexCat] do not conform to class InvariantClass's type parameter bounds [A >: Cat]
       val res5 =
           ^
<console>:14: error: type arguments [MexCat] do not conform to class InvariantClass's type parameter bounds [A >: Cat]
       new InvariantClass[MexCat]
           ^

scala> new InvariantClass[Animal]
res6: InvariantClass[Animal] = InvariantClass@28f3a218

scala> new InvariantClass[Dog]
<console>:13: error: type arguments [Dog] do not conform to class InvariantClass's type parameter bounds [A >: Cat]
       val res7 =
           ^
<console>:14: error: type arguments [Dog] do not conform to class InvariantClass's type parameter bounds [A >: Cat]
       new InvariantClass[Dog]
           ^

scala> new InvariantClass[OntheRoad]
res8: InvariantClass[OntheRoad] = InvariantClass@45ecdd32

scala> new InvariantClass[LikeFish]
res9: InvariantClass[LikeFish] = InvariantClass@fe38d1e

A <% B View Bound

View Bound 代表可被視為 B 的 A 都可以成功.

scala> trait Trat1
defined trait Trat1

scala> class Printer[A](value: A) {
     |   def print() = println(value.toString)
     | }
defined class Printer

scala> class SubPrinter[A](value: A) extends Printer(value) with Trat1 {
     |   override def print() = println("Sub print")
     | }
defined class SubPrinter

scala> implicit def int2print (i:Int) : Printer[Int] = new Printer(i)
int2print: (i: Int)Printer[Int]

scala> implicit def string2print (s:String) : Printer[String] = new Printer(s)
string2print: (s: String)Printer[String]

scala> def f1[A <% Printer[A]](a: A) = a.print()
f1: [A](a: A)(implicit evidence$1: A => Printer[A])Unit

由於隱含轉換的關係 int 、String 會轉換成 Printer,所以也都可以印出來 :

scala> f1(3)
3
scala> f1("3")
3
scala> f1(3D)
<console>:22: error: No implicit view available from Double => Printer[Double].
       f1(3D)
         ^

View Bound 如果是用 Curry 表示的話如下,將 A 轉換成 Printer 再列印出來:

scala> def f2[A](a: A)(implicit trans: A => Printer[A]) = trans(a).print()
f2: [A](a: A)(implicit trans: A => Printer[A])Unit
scala> f2(5)
5

scala> f2("123")
123

總結


  • Bound 讓我們在定義型態可以擁有更多選擇(Upper bound、Lower bound、View Bound),也更有彈性.

上一篇
Scala day 24 (variances)
下一篇
Scala day 26 (Read Files)
系列文
認識scala30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言